
#include <cstring>
#include <iostream>
#include <map>

#include "common.h"
#include "SoundManager.h"
#include "LogUtil.h"

using namespace std;

__BEGIN_NAMESPACE_DECL_

// Static member variables
SoundManager *SoundManager::_instance = NULL;

// Static methods
SoundManager& SoundManager::getInstance()
{
    if (_instance == NULL)
        _instance = new SoundManager();

    return *_instance;
}

// Constructor
//SoundManager::SoundManager(int numChannels = 16)
//    : _numChannels(numChannels)
SoundManager::SoundManager()
    : _enabled(false)
{
    // Initialize the SDL mixer library
    SDL_version compile_version;
    const SDL_version *link_version=Mix_Linked_Version();
    SDL_MIXER_VERSION(&compile_version);
    DEBUG << "compiled with SDL_mixer version: "
          << (int)compile_version.major << "."
          << (int)compile_version.minor << "."
          << (int)compile_version.patch;
    DEBUG << "running with SDL_mixer version: "
          << (int)link_version->major << "."
          << (int)link_version->minor << "."
          << (int)link_version->patch;

#define SOUNDMANAGER_CHUNKSIZE 1024
    if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 
                      2, SOUNDMANAGER_CHUNKSIZE) == -1)
    {
        ERROR << "Mix_OpenAudio: " << Mix_GetError() << endl;
        WARN  << "Error initializing SDL_mixer audio subsystem, "
                 "sound will be disabled.";
        _enabled = false;
    }
    else 
    {
        _enabled = true;

        // Allocate mixing channels
        Mix_AllocateChannels(32);
    }
}

// Destructor
SoundManager::~SoundManager()
{
    // Need to iterator over all keys in the sampleMap
    // and call Mix_FreeChunk to release the memory
    std::map<std::string, Mix_Chunk *>::iterator ptr;

    if (!_samplesMap.empty())
    {
        for (ptr = _samplesMap.begin(); ptr != _samplesMap.end(); ++ptr)
            Mix_FreeChunk (ptr->second);

        _samplesMap.clear();
    }
}

// Load Member Function
bool
SoundManager::Load (const char *filename, const char *sample_name)
{
    Mix_Chunk *sample;

    if (!_enabled)
        return false;

    if ((sample = Mix_LoadWAV(filename)) == NULL)
    {
        ERROR << "Mix_LoadWAV: " << Mix_GetError() << endl;
        return false;
    }

    std::string strSampleName = sample_name;
    std::map<std::string, Mix_Chunk *>::iterator elem_iter;

    // If a sample with this name already exists, then free it.
    elem_iter = _samplesMap.find(strSampleName);
    if (elem_iter != _samplesMap.end())
        Mix_FreeChunk(elem_iter->second);

    // Store the sample in the map
    _samplesMap[strSampleName] = sample;

    return true;
}

bool
SoundManager::Play (const char *sample_name)
{
    std::string strSampleName = sample_name;
    std::map<std::string, Mix_Chunk *>::iterator elem_iter;

    if (!_enabled)
        return false;

    elem_iter = _samplesMap.find(strSampleName);
    if (elem_iter == _samplesMap.end())
    {
        ERROR << "No sample \"" << strSampleName << "\" found" << endl;
        return false;
    }

    if (Mix_PlayChannel(-1, elem_iter->second, 0) == -1)
    {
        ERROR << "Mix_PlayChannel: " << Mix_GetError() << endl;
        return false;
    }

    return true;
}


__END_NAMESPACE_DECL_

